package Tests;

import static org.junit.Assert.*;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;

import org.junit.Before;
import org.junit.Test;

import Square.RegularSquare;
import Square.RegularSquareTeleporter;
import Square.Rock;
import Square.Square;
import Square.TransparantTeleporterSquare;

import Border.BorderType;
import Border.Direction;

@SuppressWarnings("unused")
public class TestSquares {
	
	private RegularSquare regularSquare1, regularSquare2, regularSquare3;
	
	private TransparantTeleporterSquare transparantTeleporterSquare1;
	
	private RegularSquareTeleporter regularSquareTeleporter1;
	
	
	
	@Before
	public void setUp() throws Exception {
		regularSquare1 = new RegularSquare(100, new BigDecimal(20),Direction.EAST);
		regularSquare2 = new RegularSquare(100, new BigDecimal(20),Direction.EAST);
		regularSquare3 = new RegularSquare(100, new BigDecimal(20),Direction.EAST);
		regularSquareTeleporter1 = new RegularSquareTeleporter(20, new BigDecimal(50), Direction.EAST);
		transparantTeleporterSquare1 = new TransparantTeleporterSquare(80, new BigDecimal(50), Direction.EAST);
	}

	@Test
	public final void regularConstructor_SingleCase() {
		RegularSquare regularTestSquare = new RegularSquare(10, new BigDecimal(10), Direction.EAST);
		assertEquals(10.0,0, regularTestSquare.getTemperature());
		assertEquals(new BigDecimal(10), regularTestSquare.getHumidity());
		assertEquals(BorderType.WALL, regularTestSquare.getBorderAt(Direction.EAST).getBorderType());
	}

	@Test
	public final void rockConstructor_SingleCase() {
		Rock rockTestSquare = new Rock();
		assertEquals(BorderType.WALL, rockTestSquare.getBorderAt(Direction.CEILING).getBorderType());
		assertEquals(BorderType.WALL, rockTestSquare.getBorderAt(Direction.EAST).getBorderType());
		assertEquals(BorderType.WALL, rockTestSquare.getBorderAt(Direction.FLOOR).getBorderType());
		assertEquals(BorderType.WALL, rockTestSquare.getBorderAt(Direction.NORTH).getBorderType());
		assertEquals(BorderType.WALL, rockTestSquare.getBorderAt(Direction.SOUTH).getBorderType());
		assertEquals(BorderType.WALL, rockTestSquare.getBorderAt(Direction.WEST).getBorderType());
		
	}

	@Test
	public final void teleporterConstructor_SingleCase() {
		TransparantTeleporterSquare transparantTestSquare = new TransparantTeleporterSquare(10, new BigDecimal(10), Direction.EAST);
		assertEquals(BorderType.CLOSED_DOOR, transparantTestSquare.getBorderAt(Direction.EAST).getBorderType());
		assertEquals(10.0,0, transparantTestSquare.getTemperature());
		assertEquals(new BigDecimal(10),transparantTestSquare.getHumidity());
	}

	@Test
	public final void isValidDestination_TrueCase() {
		assertTrue(regularSquareTeleporter1.isValidDestination(regularSquare1));
		assertTrue(transparantTeleporterSquare1.isValidDestination(regularSquareTeleporter1));
	}
	
	@Test
	public final void isValidDestination_FalseCase(){
		assertFalse(regularSquareTeleporter1.isValidDestination(null));
	}
	
	@Test
	public final void canAddDestination_SingleCase(){
		regularSquareTeleporter1.addDestination(regularSquare1);
	}

	@Test
	public final void getAmountOfDestinations_SingleCase(){
		regularSquareTeleporter1.addDestination(regularSquare1);
		assertEquals(1,regularSquareTeleporter1.getAmountOfDestinations());
		regularSquareTeleporter1.addDestination(regularSquare2);
		assertEquals(2,regularSquareTeleporter1.getAmountOfDestinations());
	}
	
	@Test
	public final void removeDestinations(){
		regularSquareTeleporter1.addDestination(regularSquare1);
		regularSquareTeleporter1.addDestination(regularSquare2);
		regularSquareTeleporter1.addDestination(regularSquare3);
		regularSquareTeleporter1.removeDestination(regularSquare1);
		assertEquals(2,regularSquareTeleporter1.getAmountOfDestinations());
	}
	
	@Test
	public final void pickTeleportationSquare_SingleCase(){
		regularSquareTeleporter1.addDestination(regularSquare1);
		assertEquals(regularSquare1, regularSquareTeleporter1.pickTeleportationSquare());
	}
	
	@Test
	public final void pickTeleportationSquare_DoubleCase(){
		assertTrue(checkValidRandomTeleportationSquare());
	}
	private boolean checkValidRandomTeleportationSquare(){
		regularSquareTeleporter1.addDestination(regularSquare1);
		regularSquareTeleporter1.addDestination(regularSquare2);
		regularSquareTeleporter1.addDestination(regularSquare3);
		Square square = regularSquareTeleporter1.pickTeleportationSquare();
		if (square == regularSquare1 || square == regularSquare2 ||
				square == regularSquare3)
			return true;
		else
			return false;
	}
	
	
	@Test
	public final void canTeleportTo_TrueCase(){
		regularSquareTeleporter1.addDestination(regularSquare1);
		regularSquareTeleporter1.addDestination(regularSquare2);
		assertTrue(regularSquareTeleporter1.canTeleportTo(regularSquare1));
		assertTrue(regularSquareTeleporter1.canTeleportTo(regularSquare2));
	}
	
	@Test
	public final void canTeleportTo_FalseCase(){
		regularSquareTeleporter1.addDestination(regularSquare1);
		assertFalse(regularSquareTeleporter1.canTeleportTo(regularSquare2));
	}
	
	@Test
	public final void getAllReachAbleSquares_SingleCase(){
		List<Square> array = new ArrayList<Square>();
		array.add(transparantTeleporterSquare1);
		assertEquals(array,transparantTeleporterSquare1.getAllReachableSquares());
	}

	@Test
	public final void getAllReachAbleSquares_DoubleCase(){
		List<Square> array = new ArrayList<Square>();
		array.add(transparantTeleporterSquare1);
		array.add(regularSquare1);
		transparantTeleporterSquare1.addDestination(regularSquare1);
		assertEquals(array,transparantTeleporterSquare1.getAllReachableSquares());
	}
	
	@Test
	public final void getAllReachAbleSquares_MultipleCase(){
		List<Square> array = new ArrayList<Square>();
		array.add(transparantTeleporterSquare1);
		array.add(regularSquareTeleporter1);
		array.add(regularSquare1);
		regularSquare1.mergeWith(regularSquare2, Border.Direction.NORTH);
		array.add(regularSquare2);
		transparantTeleporterSquare1.addDestination(regularSquareTeleporter1);
		transparantTeleporterSquare1.addDestination(regularSquare1);
		assertEquals(array,transparantTeleporterSquare1.getAllReachableSquares());
	}
	
	@Test
	public final void canReachSquare_FalseCase(){
		assertFalse(regularSquare1.canReachSquare(regularSquare2));
		assertFalse(regularSquare1.canReachSquare(null));
	}
	
	@Test
	public final void canReachSquare_TrueCase(){
		assertTrue(regularSquare1.canReachSquare(regularSquare1));
		transparantTeleporterSquare1.addDestination(regularSquare1);
		assertTrue(transparantTeleporterSquare1.canReachSquare(regularSquare1));
	}	
}
